package ift605.tp2.sectionB.client;

import ift605.tp2.sectionB.server.MyAdminstrableInterfaceServer;

import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

@SuppressWarnings("serial")
public class MyAdminClient  extends UnicastRemoteObject implements MyAdminInterface{

	protected MyAdminClient() throws RemoteException {
		super();
	}

	Map<Long, Long> threadMap = new HashMap<Long, Long>();
	
	public static void main(String[] args) {
		MyAdminClient client;
		try {
			client = new MyAdminClient();
			client.doSomething();
		} catch (RemoteException e) {
			e.printStackTrace();
		}
	}

	private void doSomething() {
		MyAdminstrableInterfaceServer proxy = null;
	    Scanner in = new Scanner(System.in);
	    System.out.println("Enter ipAddr of RMI Registry");
		String ipAddr = in.nextLine();
	    
		if(ipAddr == null || ipAddr.isEmpty())
		{
			ipAddr = "localhost";
		}
		
	    try {
	    	Registry registry = LocateRegistry.getRegistry(ipAddr);
			proxy = (MyAdminstrableInterfaceServer) registry.lookup("MyServerAdmin");
		} 
	    catch (Exception e) {
			e.printStackTrace();
			return;
		}
	    
	    int input = 0;
	    
	    try 
	    {
	    	Map<Long, Long> connectedClients = proxy.connect((MyAdminInterface)this);
	    	
	    	for(Long processId : connectedClients.keySet())
	    	{
	    		if(!threadMap.containsKey(processId))
	    		{
	    			threadMap.put(processId, System.currentTimeMillis() - connectedClients.get(processId));
	    		}
	    	}
	    	
	    	updateScreen();
	    	
	    	new Thread(new Displayer(this)).start();
		    do
		    {
		    	input = in.nextInt();
		    	proxy.killProcess((long) input);
		    }
		    while(input > -1);
	    	proxy.disconnect(this);
	    } 
	    catch (Exception e) 
	    {
			e.printStackTrace();
		}
		
		in.close();
	}
	
	private class Displayer implements Runnable
	{
		MyAdminClient main;

		public Displayer(MyAdminClient main)
		{
			this.main = main;
		}
		
		@Override
		public void run() {
			while(true)
			{
				try {
					Thread.sleep(5000);
					main.updateScreen();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
		
	}
	
	@Override
	public void UpdateOnConnect(Long processId) {
		System.out.println("Received connection from server");
		if(!threadMap.containsKey(processId))
		{
			threadMap.put(processId, System.currentTimeMillis());
		}
		updateScreen();
	}

	@Override
	public void UpdateOnDisconnect(Long processId) {
		System.out.println("Received disconnection from server");
		if(threadMap.containsKey(processId))
		{
			threadMap.remove(processId);
		}
		updateScreen();
	}
	
	private void updateScreen() {
		try {
	      if(System.getProperty("os.name" ).startsWith("Windows" ))
	    	  Runtime.getRuntime().exec("cls");
	      else
	    	  Runtime.getRuntime().exec("clear");
	    } 
		catch(Exception excpt) 
		{
			for(int i = 0; i < 1000; ++i)
			{
				System.out.println();
			}
		}
		
		System.out.println("Process to kill ::");

		for(Long processId : threadMap.keySet())
		{
			System.out.println("processId = " + processId+", Lifetime = " + (System.currentTimeMillis() - threadMap.get(processId)) + " milliseconds");
		}
		System.out.println("-1 : Quit");
    	System.out.println("Enter process to kill or -1 to quit");
	}

}
